package com.kaifamiao.store.system.controller;


import cn.hutool.core.lang.tree.Tree;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.kaifamiao.store.system.annotation.Premission;
import com.kaifamiao.store.system.domain.Menu;
import com.kaifamiao.store.system.domain.Role;
import com.kaifamiao.store.system.domain.User;
import com.kaifamiao.store.system.service.MenuService;
import com.kaifamiao.store.system.service.RoleService;
import com.kaifamiao.store.system.service.UserService;
import com.kaifamiao.store.system.util.JwtUtils;
import com.kaifamiao.store.system.util.Resp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/sys/user")
@Api(tags = "用户管理", value = "用户管理")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuService menuService;

    @Autowired
    private RedisTemplate redisTemplate;

    public static final String REDIS_ROLES_KEY_PRE = "roles_";

    public static final String REDIS_MENUS_KEY_PRE = "menus_";

    public static final String REDIS_PERMISSIONS_KEY_PRE = "permissions_";


    @PostMapping("/login")
    @ApiOperation(value = "用户登录", notes = "用户登录")
    @ApiResponses({
            @io.swagger.annotations.ApiResponse(code = 200, message = "登录成功"),
            @io.swagger.annotations.ApiResponse(code = 500, message = "登录失败")
    })
    public Resp login(@RequestBody  @ApiParam(name = "user", value = "用户登录信息, 必须传递其 username以及password字段", required = true
            , example = "{\"username\":\"admin\", \"password\":\"a123456\"}"
            , type = "com.kaifamiao.store.system.domain.User"
    )User user) throws Exception {
        User login = userService.login(user);

        if (ObjectUtils.isEmpty(login)){
            return Resp.error("用户名或密码错误");
        }
        login.setPassword(null);

        // 获取当前用户的权限信息
        List<Role> roles = roleService.selectRolesByUserId(login.getId());
        // 获取所有roleId
        Integer[] roleIds = roles.stream().map(Role::getId).toArray(Integer[]::new);

        List<Menu> menus = menuService.selectMenusByRoleIds(roleIds);

        /*
            redis 做缓存，
            1. 角色信息和菜单信息存到 redis 中
            2. 角色信息和菜单信息合并做权限，存到 redis 中
         */
//        redisTemplate.opsForValue().set("roles:" + login.getId(), roles);
        deleteRedisKey(REDIS_ROLES_KEY_PRE + login.getId());
        redisTemplate.opsForList().rightPushAll(REDIS_ROLES_KEY_PRE + login.getId(), roles);

        deleteRedisKey(REDIS_MENUS_KEY_PRE + login.getId());
        redisTemplate.opsForList().rightPushAll(REDIS_MENUS_KEY_PRE + login.getId(), menus);

        // 构建权限集合
        List<String> permissions = new ArrayList<>();
        for (Menu menu : menus) {
            permissions.add(menu.getMenuCode());
        }
        for (Role role : roles){
            permissions.add("ROLE_" + role.getRoleCode());
        }

        deleteRedisKey(REDIS_PERMISSIONS_KEY_PRE + login.getId());
        redisTemplate.opsForList().rightPushAll(REDIS_PERMISSIONS_KEY_PRE + login.getId(), permissions);
        JsonMapper jsonMapper = new JsonMapper();
        String token = JwtUtils.generateToken(jsonMapper.writeValueAsString(login));
        return Resp.ok(login).put("token", token);
    }

    @GetMapping("/findAll")
    @Premission("user:list")
    @ApiOperation(value = "查询所有用户", notes = "查询所有用户")
    public Resp findAll(){
        return Resp.ok(userService.list());
    }


    @GetMapping("/permissions")
    @Premission("index")
    @ApiOperation(value = "查询用户权限", notes = "查询用户权限")
    public Resp getRole(@RequestHeader("Authorization") String token, @RequestAttribute("user") User user){
        String id = user.getId();
        List<Role> roles = redisTemplate.opsForList().range(REDIS_ROLES_KEY_PRE + id, 0, -1);
        List<Menu> menus = redisTemplate.opsForList().range(REDIS_MENUS_KEY_PRE + id, 0, -1);
        List<Tree<Integer>> trees = menuService.buildTreeWithMenus(menus);

        return Resp.ok().put("roles", roles).put("menus", trees);
    }


    private void deleteRedisKey(String key) {
        if (redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }
    }

}
